﻿
/***更新****************************************************************   
*       最后更新 : ZhangJunhua   
*       更新日期 : 2010/04/15   
*       更新目的 : 增加  功能；修复bug   
*       更新版本 : 1.00   
*       更新日志 : 日志   
************************************************************************/     
  
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace System.MathTools.Statistics
{
    public class InvNormCdf
    {
        private readonly double[] __a = 
        {
		    -3.969683028665376E+01,
		    2.209460984245205E+02,
		    -2.759285104469687E+02,
		    1.383577518672690E+02,
		    -3.066479806614716E+01,
		    2.506628277459239E+00
	    };
        private readonly double[] __b = {
		    -5.447609879822406E+01,
		    1.615858368580409E+02,
		    -1.556989798598866E+02,
		    6.680131188771972E+01,
		    -1.328068155288572E+01
	    };
        private readonly double[] __c = {
		    -7.784894002430293E-03,
		    -3.223964580411365E-01,
		    -2.400758277161838E+00,
		    -2.549732539343734E+00,
		    4.374664141464968E+00,
		    2.938163982698783E+00
	    };
        private readonly double[] __d = {
		    7.784695709041462E-03,
		    3.224671290700398E-01,
		    2.445134137142996E+00,
		    3.754408661907416E+00
	    };

        private double __mean = 0.02425;
        private double __rms = 1.0 - 0.02425;
        
        public InvNormCdf(double mean, double rms)
        {
            __mean = mean;
            __rms = rms;
        }
        private double approximation4LowerRegion(double p)
        {
            double q = Math.Sqrt(-2 * Math.Log(p));
            double x = (((((__c[0] * q + __c[1]) * q + __c[2]) * q + __c[3]) * q + __c[4]) * q + __c[5]) /
                        ((((__d[0] * q + __d[1]) * q + __d[2]) * q + __d[3]) * q + 1);
            return x;
        }
        private double approximation4CentralRegion(double p)
        {
            double q = p - 0.5;
            double r = q * q;
            double x = (((((__a[0] * r + __a[1]) * r + __a[2]) * r + __a[3]) * r + __a[4]) * r + __a[5]) * q /
                        (((((__b[0] * r + __b[1]) * r + __b[2]) * r + __b[3]) * r + __b[4]) * r + 1);
            return x;
        }
        private double approximation4UpperRegion(double p)
        {
            double q = Math.Sqrt(-2 * Math.Log(1 - p));
            double x = -(((((__c[0] * q + __c[1]) * q + __c[2]) * q + __c[3]) * q + __c[4]) * q + __c[5]) /
                        ((((__d[0] * q + __d[1]) * q + __d[2]) * q + __d[3]) * q + 1);
            return x;
        }
        public double approximation(double p)
        {
            if (p > 0 && p < __mean)
                return approximation4LowerRegion(p);
            else if (p >= __mean && p <= __rms)
                return approximation4CentralRegion(p);
            else if (p >= __rms && p < 1.0)
                return approximation4UpperRegion(p);
            else
                throw new Exception("0 < confidence < 1");
        }
        
    }
}
